﻿using System;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using System.Collections.Generic;
using SysSU.UbiBroker.Interfaces;
using Newtonsoft.Json.Linq;

namespace SysSU.UbiBroker
{
    public class Domain : IDomain
    {
        private readonly string name;
        private readonly UbiBroker ubiBroker;
        private static uint id;

        internal Domain(String name, UbiBroker ubiBroker)
        {
            this.name = name;
            this.ubiBroker = ubiBroker;
        }

        #region IDomain Members

        public string Name
        {
            get { return name; }
        }

        public void Put(Tuple tuple)
        {
            string result = ubiBroker.SendMessage(getPutMessage(tuple));
        }

        public IList<Tuple> Read(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("read", pattern, filter));
            return null;
        }

        public IList<Tuple> ReadSync(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("readsync", pattern, filter));
            return null;
        }

        public Tuple ReadOne(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("readone", pattern, filter));
            return null;
        }

        public Tuple ReadOneSync(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("readonesync", pattern, filter));
            return null;
        }

        public IList<Tuple> Take(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("take", pattern, filter));
            return null;
        }

        public IList<Tuple> TakeSync(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("takesync", pattern, filter));
            return null;
        }

        public Tuple TakeOne(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("takeone", pattern, filter));
            return null;
        }

        public Tuple TakeOneSync(Pattern pattern, string filter)
        {
            string result = ubiBroker.SendMessage(getQueryMessage("takeonesync", pattern, filter));
            return null;
        }

        public object Subscribe(IReaction reaction, string eventType)
        {
            //string result = ubiBroker.SendMessage(getQueryMessage("read", pattern, filter));
            return null;
        }

        public void Unsubscribe(object reactionId)
        {
            //string result = ubiBroker.SendMessage(getQueryMessage("read", pattern, filter));
        }

        #endregion

        private string getPutMessage(Tuple tuple)
        {
            var sb = new StringBuilder();
            using (var sw = new StringWriter(sb))
            using (var jsonWriter = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
            {
                jsonWriter.WriteStartObject();
                jsonWriter.WritePropertyName("method");
                jsonWriter.WriteValue("put");
                jsonWriter.WritePropertyName("params");
                jsonWriter.WriteStartArray();
                jsonWriter.WriteValue(Name);
                jsonWriter.WriteRawValue(JsonConvert.SerializeObject(tuple.Fields));
                jsonWriter.WriteEnd();
                jsonWriter.WritePropertyName("jsonrpc");
                jsonWriter.WriteValue("2.0");
                jsonWriter.WriteEndObject();
            }

            return sb.ToString();
        }

        private string getQueryMessage(string operation, Pattern pattern, string filter)
        {
            var sb = new StringBuilder();
            using (var sw = new StringWriter(sb))
            using (var jsonWriter = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
            {
                jsonWriter.WriteStartObject();
                jsonWriter.WritePropertyName("method");
                jsonWriter.WriteValue(operation);
                jsonWriter.WritePropertyName("id");
                jsonWriter.WriteValue(++id);
                jsonWriter.WritePropertyName("params");
                jsonWriter.WriteStartArray();
                jsonWriter.WriteValue(Name);
                jsonWriter.WriteRawValue(JsonConvert.SerializeObject(pattern.Fields));
                jsonWriter.WriteValue(filter);
                //jsonWriter.WriteRawValue(); => timeout
                jsonWriter.WriteEnd();
                jsonWriter.WritePropertyName("jsonrpc");
                jsonWriter.WriteValue("2.0");
                jsonWriter.WriteEndObject();
            }

            return sb.ToString();
        }

        //private Tuple getTuple(string json)
        //{
        //    var o = JObject.Parse(json);
        //    o.            
        //}
    }
}
